<?php

declare (strict_types=1);

namespace App\Common\Model\Admin;

use App\AdminApi\Module\Admin\Enums\UserEnums;
use App\AdminApi\Module\Admin\Service\DepartmentService;
use App\Sys;
use Hyperf\Database\Model\Events\Deleted;
use Hyperf\Database\Model\Events\Saved;
use Hyperf\Database\Model\Relations\HasOne;
use Hyperf\Database\Model\SoftDeletes;
use Psr\SimpleCache\InvalidArgumentException;
use Zms\AdminHelper\Callback;
use Zms\Basics\BasicsModel;
use Zms\Guard\AuthUnit;
use Zms\HyperfCasts\{ArrjoinCasts, BoolCasts, JsonCasts, StrtotimeCasts};
use Zms\Unit\Arr;

/**
 * @property int $id
 * @property string $nickname 姓名
 * @property int $job_id 职位
 * @property int $department_id 部门
 * @property string $account 登录账号
 * @property string $password 登录密码
 * @property string $secret_key 会员密钥
 * @property string $avatar 头像
 * @property array $role_id 角色
 * @property string $data_auth_type 数据权限类型
 * @property array $auth_dep 授权部门
 * @property bool $is_super 是否超级管理员
 * @property int $status 账号状态
 * @property int $error 错误次数
 * @property int $locking 锁定时间
 * @property int $deleted_at 删除状态
 * @property int $created_at 创建时间
 * @property int $updated_at 上次更新
 * @property int $last_login 最后登录时间
 *
 *
 * @property array $role 角色名称
 * @property JobModel $job 角色名称
 * @property DepartmentModel $department 角色名称
 */
class UserModel extends BasicsModel
{
    use SoftDeletes;

    /**
     * 表名称
     * @var string|null
     */
    protected ?string $table = 'admin_user';


    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected array $fillable = [];

    protected array $appends = ['role'];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected array $casts = [
        'id' => 'int',
        'job_id' => 'int',
        'department_id' => 'int',
        'role_id' => ArrjoinCasts::class,
        'auth_dep' => JsonCasts::class,
        'status' => 'integer',
        'error' => 'integer',
        'locking' => 'integer',
        'is_super' => BoolCasts::class,
        'created_at' => StrtotimeCasts::class,
        'updated_at' => StrtotimeCasts::class,
        'last_login' => StrtotimeCasts::class
    ];


    /**
     * 数据变动事件触发清空缓存
     * @param Saved $event
     * @return void
     * @throws InvalidArgumentException
     */
    public function saved(Saved $event): void
    {
        Callback::ClearGroup(self::class);
    }


    /**
     * 数据删除时触发清空缓存
     * @param Deleted $event
     * @return void
     * @throws InvalidArgumentException
     */
    public function deleted(Deleted $event): void
    {
        Callback::ClearGroup(self::class);
    }


    /**
     * 关联职业
     * @return HasOne
     */
    public function job(): HasOne
    {
        return $this->hasOne(JobModel::class, 'id', 'job_id');
    }


    /**
     * 关联部门
     * @return HasOne
     */
    public function department(): HasOne
    {
        return $this->hasOne(DepartmentModel::class, 'id', 'department_id');
    }


    /**
     * 获取当前账号所拥有的权限
     * @return array
     */
    public function permissions(): array
    {
        return Callback::context(__METHOD__ . $this->id, function () {
            $permissions = AuthUnit::permissionValueAll('admin');
            if ($this->is_super === true || $this->id === 1) {
                return $permissions;
            }
            $all = [];
            $auths = RoleModel::whereIn('id', $this->role_id)->select(['auth'])->get()->toArray();
            foreach ($auths as $auth) {
                $all = array_merge($all, ...$auth['auth']);
            }
            return Arr::unique($all);
        });
    }


    /**
     * 获取用户的数据权限
     * @return int[]
     */
    public function dataAuth(): array
    {
        return Callback::GroupCache(self::class, "data-auth-{$this->id}", function () {
            $myid = [$this->id];
            $users = [];
            if ($this->id === UserEnums::SUPER_ADMINISTRATOR_ID || $this->is_super === UserEnums::SUPER_YES) {
                //超级管理员权限,可以看所有人的数据
                $users = self::query()->select(['id'])->get()->toArray();
            } elseif ($this->data_auth_type === UserEnums::DATA_AUTH_TYPE_SELF) {
                //仅看自己
                return $myid;
            } elseif ($this->data_auth_type === UserEnums::DATA_AUTH_TYPE_SELF_DEP) {
                if ($this->department_id === 0) {
                    return $myid;
                }
                $department = $this->department;
                if (!$department) {//部门已失效
                    return $myid;
                }
                if ($department->manage_id === $this->id) {//我是部门管理员
                    $departments = Sys::container(DepartmentService::class)->getSubordinateDepartmentId([$this->department_id]);
                    if (count($departments) === 0) {
                        return $myid;//没有部门数据,返回自身
                    }
                    $users = self::whereIn('department_id', $departments)->select(['id'])->get()->toArray();
                    if (count($users) === 0) {
                        return $myid;//没有部门数据,返回自身
                    }
                } else {//我不是部门管理员
                    return $myid;
                }
            } elseif ($this->data_auth_type === UserEnums::DATA_AUTH_TYPE_DEP) {
                //看指定部门
                if (count($this->auth_dep) === 0) {
                    return $myid;
                }
                $users = self::whereIn('department_id', array_merge(...$this->auth_dep))->select(['id'])->get()->toArray();
            }
            $authid = [...$myid, ...array_column($users, 'id')];
            return Arr::unique($authid);
        }, 1200);
    }


    /**
     * 判断是否有访问权限
     * @return bool
     * @var string|array $authorize
     */
    public function isAuthorize(string|array $authorize): bool
    {
        if ($this->isSuper() === true) {
            return true;
        }
        if (gettype($authorize) === 'string') {
            return in_array($authorize, $this->permissions());
        }
        return count(array_intersect($authorize, $this->permissions())) > 0;
    }


    /**
     * 是否是超级管理员权限
     * @return bool
     */
    public function isSuper(): bool
    {
        return $this->is_super === true || $this->id === 1;
    }


    /**
     * 获取管理员角色名称
     * @return array
     */
    public function getRoleAttribute(): array
    {
        $roleId = $this->role_id ?? [];
        $roles = [];
        if ($roleId === ['*'] || count($roleId) === 0) {
            if ($this->isSuper()) {
                $roles[] = '超级管理员';
            } else {
                return $roles;
            }
        }
        $role = Callback::context(__METHOD__, function () {
            $role = RoleModel::select(['id', 'name'])->get()->toArray();
            return Arr::map($role);
        });
        foreach ($roleId as $role_id) {
            if (isset($role[$role_id])) {
                $roles[] = $role[$role_id];
            }
        }
        return $roles;
    }
}
